import type { SelectProps } from 'antd';
import { Select } from 'antd';
import { get, getDeepth, invokeFunc, shouldUpdate, toLevelPath, wrapperCls } from '../utils';
import { useLocale, useOutterComponents } from '../utils/hooks';
import { useContext } from 'react';
import { RuleTreeContext, RuleTreePropsContext } from './RuleTreeContext';
import React from 'react';
import { fieldNamesTreeMap } from '../utils/global';
import type { FieldNames } from '../types';
import styled from 'styled-components';

const defaultOptions = ['and', 'or'] as const;

const Wrapper = styled.div<{ $marginRight: number }>`
  margin-right: ${props => props.$marginRight}px;
`;

export default function RelationNode(props: {
  name: number | null;
  path: (string | number)[];
}) {
  const { localeMap } = useLocale();
  const { prefixCls } = useContext(RuleTreeContext);
  const { gap, uid, relationRender, defaultRelationValue, relationFormItemRender, onRelationChange, relationFormItemProps } = useContext(RuleTreePropsContext);
  const { Form } = useOutterComponents();
  const { relation: RelationKey, children: ChildrenKey } = fieldNamesTreeMap.get(uid) as Required<FieldNames>;
  const form = Form.useFormInstance();
  const cls = wrapperCls(prefixCls);
  const initOptions = defaultOptions.map(item => ({ label: localeMap[item], value: item }));

  const getFields = () => ({
    levelPath: toLevelPath(props.path),
    count: form.getFieldValue([...props.path, ChildrenKey])?.length || 0,
    deepth: getDeepth(props.path),
    index: props.name || 0,
  });

  return (
    <Wrapper className={`${cls}-relation`} $marginRight={(gap as [number, number])[0]}>
      <Form.Item
        shouldUpdate={(prev, next) => {
          if (!relationFormItemRender && !relationRender) {
            return false;
          }

          const objA: any = get(prev, props.path) || {};
          const objB: any = get(next, props.path) || {};

          return shouldUpdate(objA, objB, ChildrenKey);
        }}
        noStyle
      >
        {
          () => {
            const relationDom = invokeFunc(() => {
              const defaultDom = (
                <Select
                  style={{ width: 'auto', minWidth: 65 }}
                  options={initOptions}
                  onChange={(value, option) => {
                    onRelationChange?.(value, option, getFields());
                  }}
                />
              );

              if (relationRender) {
                const dom = relationRender(defaultDom, getFields());

                if (React.isValidElement<SelectProps>(dom)) {
                  return React.cloneElement<SelectProps>(dom, {
                    onChange(value, option) {
                      dom.props.onChange?.(value, option);
                      onRelationChange?.(value, option, getFields());
                    },
                  });
                }

                return dom;
              }

              return defaultDom;
            });

            const defaultDom = (
              <Form.Item initialValue={defaultRelationValue} noStyle name={props.name === null ? RelationKey : [props.name, RelationKey]} {...relationFormItemProps}>
                {relationDom}
              </Form.Item>
            );

            return relationFormItemRender?.(defaultDom, getFields()) || defaultDom;
          }
        }
      </Form.Item>
    </Wrapper>
  );
}